package com.example.aspect;

import com.example.annotation.AuditLog;
import com.example.service.AuditLogService;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import jakarta.servlet.http.HttpServletRequest;

/**
 * 审计日志切面
 */
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class AuditLogAspect {

    private final AuditLogService auditLogService;
    private final ObjectMapper objectMapper;

    @Around("@annotation(auditLog)")
    public Object around(ProceedingJoinPoint point, AuditLog auditLog) throws Throwable {
        long startTime = System.currentTimeMillis();
        
        // 获取当前用户信息
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        String userId = auth != null && auth.isAuthenticated() ? auth.getName() : "anonymous";
        String username = userId;

        // 获取请求信息
        HttpServletRequest request = getCurrentRequest();
        String clientIp = getClientIp(request);
        String userAgent = request != null ? request.getHeader("User-Agent") : "";

        // 创建审计日志对象
        com.example.model.AuditLog logEntity = com.example.model.AuditLog.create(
            userId, username, auditLog.operation(), auditLog.module(), auditLog.description()
        );

        // 设置请求信息
        if (request != null) {
            logEntity.withRequest(request.getMethod(), request.getRequestURI(), getRequestParams(request));
        }
        logEntity.withClient(clientIp, userAgent);
        logEntity.withRiskLevel(auditLog.riskLevel());

        try {
            // 执行目标方法
            Object result = point.proceed();
            
            // 计算执行时间
            long executionTime = System.currentTimeMillis() - startTime;
            
            // 记录成功结果
            String resultStr = auditLog.includeResult() ? serializeResult(result) : null;
            logEntity.withResult(com.example.model.AuditLog.OperationStatus.SUCCESS, resultStr, executionTime);
            
            // 异步保存日志
            auditLogService.logAsync(logEntity);
            
            return result;
            
        } catch (Exception e) {
            // 计算执行时间
            long executionTime = System.currentTimeMillis() - startTime;
            
            // 记录失败结果
            logEntity.withError(e.getMessage());
            logEntity.setExecutionTime(executionTime);
            
            // 异步保存日志
            auditLogService.logAsync(logEntity);
            
            throw e;
        }
    }

    /**
     * 获取当前请求
     */
    private HttpServletRequest getCurrentRequest() {
        try {
            ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
            return attributes != null ? attributes.getRequest() : null;
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 获取客户端IP
     */
    private String getClientIp(HttpServletRequest request) {
        if (request == null) {
            return "unknown";
        }
        
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        
        return ip != null ? ip : "unknown";
    }

    /**
     * 获取请求参数
     */
    private String getRequestParams(HttpServletRequest request) {
        try {
            java.util.Map<String, String[]> paramMap = request.getParameterMap();
            if (paramMap.isEmpty()) {
                return null;
            }
            
            // 过滤敏感参数
            java.util.Map<String, String[]> filteredMap = new java.util.HashMap<>();
            for (java.util.Map.Entry<String, String[]> entry : paramMap.entrySet()) {
                String key = entry.getKey().toLowerCase();
                if (!key.contains("password") && !key.contains("token") && 
                    !key.contains("secret") && !key.contains("key")) {
                    filteredMap.put(entry.getKey(), entry.getValue());
                }
            }
            
            return objectMapper.writeValueAsString(filteredMap);
        } catch (Exception e) {
            log.warn("序列化请求参数失败: {}", e.getMessage());
            return null;
        }
    }

    /**
     * 序列化结果
     */
    private String serializeResult(Object result) {
        try {
            if (result == null) {
                return null;
            }
            
            // 限制结果长度，避免日志过大
            String resultStr = objectMapper.writeValueAsString(result);
            if (resultStr.length() > 1000) {
                return resultStr.substring(0, 1000) + "...";
            }
            
            return resultStr;
        } catch (Exception e) {
            log.warn("序列化结果失败: {}", e.getMessage());
            return "序列化失败";
        }
    }
}
